@file:UseSerializers(ItemVariantSerializer::class, FluidVariantSerializer::class, StatSerializer::class)

package com.lalameow.researchstation.api.technology

import com.lalameow.researchstation.util.serialization.FluidVariantSerializer
import com.lalameow.researchstation.util.serialization.ItemVariantSerializer
import com.lalameow.researchstation.util.serialization.StatSerializer
import dev.architectury.fluid.FluidStack
import dev.architectury.hooks.fluid.fabric.FluidStackHooksFabric
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import kotlinx.serialization.UseSerializers
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariantAttributes
import net.fabricmc.fabric.api.transfer.v1.item.ItemVariant
import net.minecraft.item.ItemStack
import net.minecraft.stat.Stat
import net.minecraft.stat.Stats
import net.minecraft.text.MutableText
import net.minecraft.text.Text
import net.minecraft.text.TranslatableText
import net.minecraft.util.Identifier

@Suppress("UnstableApiUsage")
@Serializable
data class FluidResource(override val type: FluidVariant, override val count: Long) :
    TechnologyResource<FluidVariant> {
    constructor(fluid: FluidStack) : this(FluidStackHooksFabric.toFabric(fluid), fluid.amount)

    override val name = FluidVariantAttributes.getName(type)!!

    override fun test(input: FluidVariant) = type.fluid == input.fluid && type.nbtMatches(input.nbt)
}

@Suppress("UnstableApiUsage")
@Serializable
data class ItemResource(override val type: ItemVariant, override val count: Long) :
    TechnologyResource<ItemVariant> {
    constructor(item: ItemStack) : this(ItemVariant.of(item), item.count.toLong())

    override val name = type.item.name!!

    override fun test(input: ItemVariant) = type.matches(input.toStack())
}

@Serializable
class StatResource(override val type: Stat<out @Contextual Any>, override val count: Long) :
    TechnologyResource<Stat<*>> {
    override val name: Text =
        if (type.type == Stats.CUSTOM) TranslatableText((type as Stat<Identifier>).getStatTranslationKey())
        else (type.type.name as MutableText).append(": ${type.name}")

    override fun test(input: Stat<*>) = type == input

    companion object {
        private fun Stat<Identifier>.getStatTranslationKey(): String {
            return "stat." + value.toString().replace(':', '.')
        }
    }
}
